<template>
  <a-modal
    v-model:open="open"
    title="用户信息"
    ok-text="提交"
    centered
    @ok="handleOk"
  >
    <a-form
      :model="formState"
      name="basic"
      autocomplete="off"
      layout="vertical"
    >
      <a-form-item
        label="头像"
        class="!mt-[20px] !mb-[5px] last:mb-0"
      >
        <div class="relative inline-block">
          <a-upload
            v-model:file-list="fileList"
            name="avatar"
            list-type="picture-card"
            class="avatar-uploader overflow-hidden"
            :show-upload-list="false"
            :before-upload="beforeUpload"
            @change="handleChange"
          >
            <template v-if="formState.userAvatar">
              <img
                :src="formState.userAvatar"
                alt="avatar"
                class="pointer-events-none h-full w-full rounded-[8px] object-cover"
              />
            </template>
            <template v-else>
              <loading-outlined v-if="loading"></loading-outlined>
              <plus-outlined v-else></plus-outlined>
              <div class="ant-upload-text text-[12px]">点击上传</div>
            </template>
          </a-upload>
        </div>
      </a-form-item>
      <a-form-item
        class="!mb-[15px] last:mb-0"
        name="userName"
        label="用户名"
      >
        <a-input
          class="h-10 text-[13px]"
          v-model:value="formState.userName"
          placeholder="请输入用户名~"
        >
        </a-input>
      </a-form-item>
      <a-form-item
        class="!mb-[15px] last:mb-0"
        name="userProfile"
        label="简介"
      >
        <a-textarea
          class="!h-[90px] !resize-none !pt-[10px] !pb-[10px] text-[13px]"
          v-model:value="formState.userProfile"
          placeholder="请输入简介~"
        >
        </a-textarea>
      </a-form-item>
      <a-form-item
        class="!mb-[35px]"
        name="userRole"
        label="角色"
      >
        <a-select
          class="!h-[40px] text-[13px]"
          v-model:value="formState.userRole"
          :options="UserRoleOptions"
        >
        </a-select>
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script lang="ts" setup>
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue';
import { updateUser } from '@/api/userController';
import type { UploadChangeParam, UploadFile } from 'ant-design-vue';
import { getBase64 } from '@/utils/tool';
import { message } from 'ant-design-vue';
import { useUserStore } from '@/stores/user';
import { UserRoleOptions } from '@/constants/role.enum';
import { eventBus, EventNames } from '@/utils/eventBus';
import { inject, onMounted, onUnmounted } from 'vue';

const open = ref<boolean>(false);

const userStore = useUserStore();

// 注入全局图片编辑弹窗方法
const showPictureCropperModal = inject<(imageUrl?: string) => void>('showPictureCropperModal');

// 表单数据
const formState = reactive<Partial<API.UserVO>>({
  id: undefined,
  userName: '',
  userProfile: '',
  userRole: '',
  userAvatar: ''
});

const fileList = ref([]);
const loading = ref<boolean>(false);

const emit = defineEmits(['submitSuccess']);

const handleChange = (info: UploadChangeParam) => {
  // 文件状态变化时处理（主要用于显示loading状态）
  if (info.file.status === 'uploading') {
    loading.value = true;
    return;
  }
  if (info.file.status === 'error') {
    loading.value = false;
    message.error('上传失败');
  }
};

const beforeUpload = (file: UploadFile) => {
  console.log('beforeUpload 被调用', file);

  // 验证文件类型
  const isJpgOrPng = file.type?.includes('image/') ?? false;
  if (!isJpgOrPng) {
    message.error('只能上传图片文件！');
    return false;
  }

  // 验证文件大小
  const isLt2M = file.size ? file.size / 1024 / 1024 < 2 : false;
  if (!isLt2M) {
    message.error('图片大小不能超过 2MB！');
    return false;
  }

  // 获取文件对象（优先使用 originFileObj，否则使用 file 本身）
  const fileObj = file.originFileObj || (file as unknown as File);

  if (!fileObj) {
    message.error('无法获取文件对象');
    return false;
  }

  // 转换为base64后打开裁切弹窗（不实际上传到服务器）
  loading.value = true;
  getBase64(
    fileObj as Blob,
    (base64Url: string) => {
      loading.value = false;
      // 打开图片裁切弹窗
      if (showPictureCropperModal) {
        showPictureCropperModal(base64Url);
      } else {
        // 如果没有裁切弹窗，直接使用原图
        formState.userAvatar = base64Url;
        message.success('图片上传成功！');
      }
    },
    (error: Error) => {
      loading.value = false;
      message.error('图片读取失败：' + error.message);
      console.error('Base64转换失败：', error);
    }
  );

  // 返回false阻止实际上传到服务器
  return false;
};

/**
 * 显示弹窗
 * @param type 操作类型：'add' 新增 | 'edit' 编辑
 * @param data 编辑时的用户数据（新增时可不传）
 */
const showModal = (data: API.UserVO) => {
  formState.id = data.id || undefined;
  formState.userName = data.userName || '';
  formState.userAccount = data.userAccount || '';
  formState.userProfile = data.userProfile || '';
  formState.userRole = data.userRole || '';
  formState.userAvatar = data.userAvatar || '';
  open.value = true;
};

/**
 * 提交事件
 */
const handleOk = async () => {
  try {
    const res = await updateUser(formState as API.UserUpdateRequest);
    const loginUser = userStore.loginUser;

    if (res.data?.code === 0) {
      message.success('更新成功');
      open.value = false;

      // 如果更新的是当前登录用户，更新 store
      if (formState.id === loginUser.id) {
        // 合并更新用户信息，保留原有字段并更新新字段
        userStore.setLoginUser({
          ...loginUser,
          ...formState
        } as API.LoginUserVO);
      }

      // 发出本地事件（用于父组件监听）
      emit('submitSuccess');

      // 发出全局事件（用于跨组件通信，如刷新表格）
      eventBus.emit(EventNames.USER_UPDATE_SUCCESS, formState);
    } else {
      message.error(res.data?.message || '更新失败');
    }
  } catch (error) {
    console.error('更新失败：', error);
    message.error('更新失败');
  }
};

// 监听头像裁切完成事件
const handleAvatarCropped = (croppedImageUrl: unknown) => {
  if (typeof croppedImageUrl === 'string') {
    formState.userAvatar = croppedImageUrl;
    message.success('图片裁切成功！');
  }
};

onMounted(() => {
  // 监听头像裁切完成事件
  eventBus.on(EventNames.AVATAR_CROPPED, handleAvatarCropped);
});

onUnmounted(() => {
  // 移除事件监听
  eventBus.off(EventNames.AVATAR_CROPPED, handleAvatarCropped);
});

// 暴露 showModal 方法
defineExpose({
  showModal
});
</script>

<style lang="scss" scoped>
::v-deep(.ant-select-selector) {
  height: 40px !important;

  .ant-select-selection-item {
    line-height: 38px !important;
  }
}
</style>
